package com.kinyx.hibernate.type.descriptor.java;

import java.util.BitSet;

import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.AbstractTypeDescriptor;

@SuppressWarnings("serial")
public class BitSetBasicTypeDescriptor extends AbstractTypeDescriptor<BitSet> {

	private static final String DELIMITER = ",";

	public static final BitSetBasicTypeDescriptor INSTANCE = new BitSetBasicTypeDescriptor();

	public BitSetBasicTypeDescriptor() {
		super(BitSet.class);
	}

	@Override
	public String toString(final BitSet value) {
		final StringBuilder builder = new StringBuilder();
		for (final long token : value.toLongArray()) {
			if (builder.length() > 0) {
				builder.append(DELIMITER);
			}
			builder.append(Long.toString(token, 2));
		}
		return builder.toString();
	}

	@Override
	public BitSet fromString(final String string) {
		if ((string == null) || string.isEmpty()) {
			return null;
		}
		final String[] tokens = string.split(DELIMITER);
		final long[] values = new long[tokens.length];

		for (int i = 0; i < tokens.length; i++) {
			values[i] = Long.valueOf(tokens[i], 2);
		}
		return BitSet.valueOf(values);
	}

	@Override
	@SuppressWarnings({
			"unchecked"
	})
	public <X> X unwrap(final BitSet value, final Class<X> type, final WrapperOptions options) {
		if (value == null) {
			return null;
		}
		if (BitSet.class.isAssignableFrom(type)) {
			return (X) value;
		}
		if (String.class.isAssignableFrom(type)) {
			return (X) this.toString(value);
		}
		throw this.unknownUnwrap(type);
	}

	@Override
	public <X> BitSet wrap(final X value, final WrapperOptions options) {
		if (value == null) {
			return null;
		}
		if (String.class.isInstance(value)) {
			return this.fromString((String) value);
		}
		if (BitSet.class.isInstance(value)) {
			return (BitSet) value;
		}
		throw this.unknownWrap(value.getClass());
	}
}
